package org.jb.coinche.server.notify.impl;

import java.util.ArrayList;
import java.util.Set;

import org.jb.coinche.client.notify.Notification;
import org.jb.coinche.client.notify.NotificationService;
import org.jb.coinche.client.notify.Notifications;
import org.jb.coinche.server.notify.NotificationManager;
import org.jb.coinche.server.notify.NotificationProvider;
import org.jb.coinche.server.rooms.RoomScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;

@RoomScoped
public class NotificationServiceImpl implements NotificationService, NotificationManager {

	private static final Logger logger = LoggerFactory.getLogger(NotificationServiceImpl.class);
	
	/*
	 * (non-Javadoc)
	 * @see org.jb.coinche.client.notify.NotificationService#getNotification(long)
	 */
	public Notifications getNotification(long checkpoint) {
		synchronized( lock ) {
			if (checkpoint >= this.checkpoint) {	
				try {
					logger.debug("No notification available => locking");
					lock.wait( 2 * 60 * 1000 );
				} catch (InterruptedException e) {
					logger.debug("Timeout waiting for notification");
					throw new IllegalArgumentException("timeout");
				}
			}
		
			ArrayList<Notification> notifications = new ArrayList<Notification>();
			for( NotificationProvider provider : providers ) {
				provider.notify(notifications, checkpoint);
			}
			
			Notifications n = new Notifications();
			n.setNotifications( notifications );
			n.setCheckpoint( this.checkpoint );
			
			logger.debug("Sending {} notifications", n.getNotifications().size() );
			
			return n;
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.jb.coinche.server.notify.NotificationManager#wakeup()
	 */
	public void wakeup() {
		synchronized( lock ) {
			lock.notifyAll();
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.jb.coinche.server.notify.NotificationManager#getNextId()
	 */
	public long getNextId() {
		synchronized( lock ) {
			return ++checkpoint;
		}
	}
	
	@Inject
	private Set<NotificationProvider> providers;
	private Object lock = new Object();
	private long checkpoint = 0;

}
